前情提要:昨天繼續擴增todos後,已經可以好好管理非預期的路由了,不管是走錯地方的需要Redirect或是根本沒那頁的404,都可以好好處理它們。今天就來看看Query Parameters吧!
Query Parameters其實就是指window.location.search,也就是會出現在網址列的參數(如下圖問號(?)後的部分)。
這些參數可以指引我們如何處理資料,所以今天的目標就是做todos的過濾!
以結果來看的話就是增加下圖紅框那塊
之前Link的操作,都是很簡單的在to屬性設定string來指定要連接的位置,如下:
<Link to="/about">About</Link>
其實to也接受object,在object內有四個屬性可以用,分別為:
今天會需要的對象是search,除了state之外的屬性,如果不想把它拆開設定在object裡,其實也可以跟串燒一樣把全部的內容組成字串丟給to就好了,如下:
<Link to="/todos?state=active#123">Active</Link
為了維護整潔的空間,我還是使用object設定好了~!
我新增了一個TodoFilterConatiner.js檔案,處理步驟如下:
import React from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
const filterInfo = [
{to: {pathname: "/todos"}, text: "All"},
{to: {search: "?state=active"}, text: "Active"},
{to: {search: "?state=completed"}, text: "Completed"}
]
const TodoFilterConatiner = ({todoLength, activeLength}) => todoLength ? (
<div className="state">
<span>{activeLength} 項未完成</span>
<ul className="state-filter-list">
{ filterInfo.map(({to, text}, index) => (
<li key={index}>
<Link to={to} className="state-filter-item">{text}</Link>
</li>
))}
</ul>
</div>
) : null;
export default connect(({todoList}) => ({
todoLength: todoList.length,
activeLength: todoList.filter(({completed}) => !completed).length
}))(TodoFilterConatiner);
處理完search後,順利的話可以看到點擊anchor後,網址列尾端會帶上我們預期的參數state,如下:
接著,我們就要回到TodoListContainer.js過濾我們的條件啦
這部分會看到幾個之前沒提過的新面孔,withRouter和compose。
總而言之就是使用compose組合越來越多的high-order components,並使用withRouter取得router訊息,主要處理資料的地方在mapStateToProps,說明如下:
取得state後就可以做completed判斷,就可以使用filter來過濾todoList了。
import { compose } from 'redux';
import { withRouter } from 'react-router-dom';
// ... TodoListContainer component
const mapStateToProps = ({todoList}, {location:{search}}) => {
let params = new URLSearchParams(search.substring(1));
let state = params.get('state');
let completed = state === "completed";
let todo = state ? todoList.filter(item => item.completed === completed) : todoList;
return { todo };
}
export default compose(
withRouter,
connect(mapStateToProps, {
completeTodo, removeTodo
})
)(TodoListContainer);
最後,記得在Todo.js匯入這次新增的component就可以完成並測試了。
實際操作畫面如下:
github傳送門
今日總結:todos這邊暫時玩得差不多了,明天往news那邊去開墾吧!